﻿using CommonUtils;
using ControllerGenerator.Structs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ControllerGenerator.Commands
{
    class DbControllerGenerator
    {
        public static void Handler(object sender, EventArgs e)
        {
            var document = EditorUtil.GetTextDocument();
            var classCode = document.GetText();
            if (classCode.IsEmpty())
            {
                EditorUtil.ShowMessage("请选中代码文件");
                return;
            }
            if (!classCode.Contains(": DbEntity"))
            {
                EditorUtil.ShowMessage("请选中表结构文件:\r\n" + classCode);
                return;
            }
            var className = StringUtil.GetBetween(classCode, "public class ", " : DbEntity", false);

            //DbSet
            var needMigration = false;
            var dbFile = document.GetFullName().Combine("../../Database/Db.cs");
            var dbCode = FileUtil.GetText(dbFile);
            if (dbCode.IsNotEmpty())
            {
                var endMark = "    }\r\n}";
                var targetCode = "        public DbSet<{}> {}s { get; set; }\r\n".Format(className, className);
                if (!dbCode.Contains(targetCode))
                {
                    dbCode = dbCode.Replace(endMark, "\r\n" + targetCode + endMark);
                    FileUtil.SaveTo(dbFile, dbCode);
                    needMigration = true;
                }
            }

            var namespace_ = StringUtil.GetBetween(classCode, "namespace ", "\n", false).Trim();
            if (namespace_.IsEmpty())
                namespace_ = "DefaultNamespace";
            var parentspace = namespace_;
            if (parentspace.Contains('.'))
                parentspace = parentspace.Substring(0, parentspace.LastIndexOf('.'));
            //类注释
            var classSchame = StringUtil.GetBetween(classCode, "[SwaggerSchema(", "public class", false);
            classSchame = StringUtil.GetBetween(classSchame, "\"", "\"", false);

            classCode = StringUtil.SubstringFrom(classCode, "class");

            //注释+字段
            var fields = new List<Field>();
            var fieldSchames = StringUtil.GetBetweens(classCode, "SwaggerSchema", " { get; set; }", true);
            foreach (var fieldSchame in fieldSchames)
            {
                if (fieldSchame.CountOf('\n') > 3)
                    continue;
                var schame = StringUtil.GetBetween(fieldSchame, "\"", "\"", false);
                var name = StringUtil.GetBetween(fieldSchame, "public ", " { get; set; }", false);
                if (name.Contains('\n'))
                    continue;
                var cells = name.Split(' ');
                var type = cells[0];
                name = cells[1];
                var field = new Field();
                field.Name = name;
                field.Type = type;
                field.Schame = schame;
                fields.Add(field);
            }
            fieldSchames = StringUtil.GetBetweens(classCode, "SwaggerSchema", " { set; get; }", true);
            foreach (var fieldSchame in fieldSchames)
            {
                if (fieldSchame.CountOf('\n') > 3)
                    continue;
                var schame = StringUtil.GetBetween(fieldSchame, "\"", "\"", false);
                var name = StringUtil.GetBetween(fieldSchame, "public ", " { set; get; }", false);
                if (name.Contains('\n'))
                    continue;
                var cells = name.Split(' ');
                var type = cells[0];
                name = cells[1];
                var field = new Field();
                field.Name = name;
                field.Type = type;
                field.Schame = schame;
                fields.Add(field);
            }

            //无注释字段
            var fieldNames = StringUtil.GetBetweens(classCode, "public ", " { get; set; }", true);
            foreach (var fieldName in fieldNames)
            {
                var name = StringUtil.GetBetween(fieldName, "public ", " { get; set; }", false);
                if (name.Contains('\n'))
                    continue;
                var cells = name.Split(' ');
                var type = cells[0];
                name = cells[1];
                var field = new Field();
                field.Name = name;
                field.Type = type;
                if (fields.FirstOrDefault(m => m.Name == name) == null)
                    fields.Add(field);
            }
            fieldNames = StringUtil.GetBetweens(classCode, "public ", " { set; get; }", true);
            foreach (var fieldName in fieldNames)
            {
                var name = StringUtil.GetBetween(fieldName, "public ", " { set; get; }", false);
                if (name.Contains('\n'))
                    continue;
                var cells = name.Split(' ');
                var type = cells[0];
                name = cells[1];
                var field = new Field();
                field.Name = name;
                field.Type = type;
                if (fields.FirstOrDefault(m => m.Name == name) == null)
                    fields.Add(field);
            }

            //请求参数
            var filterFields = new StringBuilder();
            var filterLambdas = new StringBuilder();
            foreach (var field in fields)
            {
                if (!field.Type.Remove("?").Equals("string", "double", "int", "bool", "DateTime", "long", "float"))
                    continue;
                if (filterFields.Length > 0)
                    filterFields.AppendLine(",");
                filterFields.Append("            [SwaggerParameter(\"{}\")] {}? {}",
                    field.Schame.IsEmpty(field.Name), field.Type.RemoveChar('?'), field.LowerFirst);
                filterLambdas.LineAppend("            .And({}.IsNotEmpty(), m => m.{} == {})",
                    field.LowerFirst, field.Name, field.LowerFirst);
            }

            var controllerCode = ResourceUtil
                                 .GetText(typeof(DbControllerGenerator).Assembly, "UserController.txt")
                                 .Replace("@namespace", namespace_)
                                 .Replace("@parentspace", parentspace)
                                 .Replace("@Name", className)
                                 .Replace("@ControllerTitle", classSchame.IsEmpty(className))
                                 .Replace("@FilterFields", filterFields.ToString())
                                 .Replace("@FilterLambdas", filterLambdas.ToString());
            var path = document.GetFullName().Combine("../../Controllers/" + className + "Controller.cs");
            FileUtil.SaveTo(path, controllerCode);
            EditorUtil.ShowMessage("代码已生成: " + path);
            if (needMigration)
            {
                Clipboard.SetText("add-migration updateX");
                EditorUtil.ShowMessage("数据迁移命令: add-migration updateX 已复制到剪切板");
            }
        }
    }
}

